import React, { HTMLAttributes, ReactNode, useCallback, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import Button from '../Button/Button';
import Left from '../icons/left.svg';
import Right from '../icons/right.svg';
import DoubleLeft from '../icons/doubleLeft.svg';
export interface PaginationProps extends HTMLAttributes {
defaultPage?: number;
totalSrc: number;
perPage?: number;
moreTool?: boolean;
goTool?: boolean;
statistic?: boolean;
callback?: (currentPage: number, start: number, end: number) => void;
}
const PaginationStyled = styled.div`
display: flex;
align-items: center;
gap: 8px;
`;
const PageButton = styled(Button).attrs({
type: 'text',
radius: true,
border: 'none'
})`
height: 2em;
min-width: 2em;
padding: 0 2px;
border: 1px solid #d9d9d9;
outline: none;
box-shadow: none;
&:hover {
-webkit-filter: brightness(100%);
border: 1px solid #1890ff;
}
`;
const PageWrap = styled.div`
display: flex;
align-items: center;
gap: 8px;
`;
const InputStyled = styled.input`
max-width: 4em;
height: 2em;
outline: none;
border: 1px solid #d9d9d9;
border-radius: 2px;
padding: 10px;
&:focus {
border: 1px solid #1890ff;
box-shadow: 0 0 4px 1px rgba(24, 144, 255, 0.2);
}
`;
type MoreProps = Pick;
const MoreStyled = styled(PageButton)`
display: ${(props: MoreProps) => (props.moreTool ? 'inline-flex' : 'none')};
`;
const GoStyled = styled.div`
display: ${(props: MoreProps) => (props.goTool ? 'inline-flex' : 'none')};
gap: 8px;
align-items: center;
`;
const Pagination: React.FC = (props) => {
const {
children,
statistic,
goTool,
moreTool,
perPage,
callback,
defaultPage,
totalSrc,
...rest
} = props;
const totalPage = Math.ceil(Math.abs(totalSrc!) / perPage!);
const [n, setN] = useState(1); // 当前处于那一页
const pageWrap = useRef(null);
const inputRef = useRef(null);
const dom: ReactNode[] = [];
useEffect(() => {
setN(Math.abs(defaultPage! > totalPage ? 1 : defaultPage!));
});
// eslint-disable-next-line consistent-return
const createPageNumber = (i: number): number => {
let endPage = 0;
if (totalPage <= 5) {
endPage = i + 1;
}
if (totalPage > 5 && n <= 5) {
endPage = i + 1;
}
if (totalPage > 5 && n > 5) {
endPage = n - 2 + i;
if (n + 5 > totalPage) {
endPage = n - 4 + i;
}
}
return endPage;
};
// 初始化
for (let i = 0; i < (totalPage > 5 ? 5 : totalPage); i++) {
dom.push({createPageNumber(i)});
}
const call = useCallback((numberPage: number) => {
if (perPage) {
let start: number;
let end: number;
if (numberPage === 1) {
start = 0;
} else {
start = perPage * numberPage - perPage;
}
if (perPage * numberPage > totalSrc) {
end = totalSrc;
} else {
end = perPage * numberPage;
}
callback?.(numberPage, start, end);
}
}, []);
// 左侧被点击
const leftClick = () => {
if (n > 1) {
setN((state) => state - 1);
call(n - 1);
}
};
// 右侧被点击
const rightClick = () => {
if (n < totalPage) {
setN(() => n + 1);
call(n + 1);
}
};
// page点击
const WrapClick = (e: React.MouseEvent) => {
const el = e.target as HTMLButtonElement;
if (el.tagName.toLowerCase() === 'button') {
const numberPage = parseInt(el.innerText, 10);
setN(numberPage);
call(numberPage);
}
};
// 更多被点击
const moreClick = () => {
if (n + 5 < totalPage) {
setN(() => n + 5);
call(n + 5);
} else if (n === totalPage) {
return null;
} else {
setN(totalPage);
call(totalPage);
}
};
// 输入新的页码
const inputNewPageNumber = () => {
if (inputRef.current?.value) {
const pageNumber = parseInt(inputRef.current?.value, 10) || 1;
if (pageNumber >= totalPage && pageNumber) {
setN(totalPage);
call(totalPage);
} else {
setN(pageNumber);
call(pageNumber);
}
}
};
useEffect(() => {
if (pageWrap.current) {
const childList = Array.from(pageWrap.current.children as unknown as HTMLButtonElement[]);
childList.forEach((item) => {
if (item.innerText === n.toString()) {
item.style.color = '#1890ff';
}
});
}
});
return (
) => {
WrapClick(e);
}}
role="presentation"
>
{dom}
= totalPage ? 'not-allowed' : 'pointer',
border: 'none',
backgroundColor: 'inherit',
display: moreTool ? 'block' : 'none'
}}
>
= totalPage ? 'not-allowed' : 'pointer' }}
>
跳至
页
共
{n}/{totalPage}
页
);
};
Pagination.defaultProps = {
defaultPage: 1,
callback: () => {},
perPage: 5,
moreTool: false,
statistic: false,
goTool: false
};
export default React.memo(Pagination);